package com.hps.demo.configurer.rpc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hps.demo.entity.Request;
import com.hps.demo.entity.Response;
import com.hps.demo.netty.client.NettyClient;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;

import com.hps.demo.service.InfoUserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @author heps
 * @since 2020/8/15
 */
@Slf4j
@AllArgsConstructor
@Component
public class RpcFactory<T> implements InvocationHandler {

  private NettyClient nettyClient;

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (method.getDeclaringClass() == Object.class) {
      return method.invoke(this, args);
    }
    Request request = new Request();
    request.setClassName(method.getDeclaringClass().getName());
    request.setMethodName(method.getName());
    request.setParameters(args);
    request.setParameterTypes(method.getParameterTypes());
    request.setId(UUID.randomUUID().toString());

    Object result = nettyClient.send(request);
    Class<?> returnType = method.getReturnType();
    Response response = JSON.parseObject(result.toString(), Response.class);
    if (response.getCode() == 1) {
      throw new Exception(response.getErrorMsg());
    }
    if (Objects.isNull(response.getData())) {
      return null;
    } else if (returnType.isPrimitive() || String.class.isAssignableFrom(returnType)) {
      return response.getData();
    } else if (Collection.class.isAssignableFrom(returnType)){
      return JSONArray.parseArray(response.getData().toString(),Object.class);
    } else if (Map.class.isAssignableFrom(returnType)){
      return JSON.parseObject(response.getData().toString(), Map.class);
    } else {
      Object data = response.getData();
      return JSONObject.parseObject(data.toString(), returnType);
    }
  }
}
